package annotool.select;

import ij.ImagePlus;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Vector;

import annotool.io.DataInput;
import annotool.io.DataInputDynamic;
import annotool.io.LabelReader;

import mpicbg.imagefeatures.Feature;
import mpicbg.imagefeatures.FloatArray2DSIFT;
import mpicbg.imagefeatures.fratios;
import mpicbg.imagefeatures.fweights;
import mpicbg.models.PointMatch;
import mpicbg.models.quickSort;


public class ConsensusSelection 
{
	public final static String DEFAULT_DIR = "k150/"; //"stage4_6/" for embryos
	public final static String DEFAULT_EXT = ".jpg";  //".png"; 
	public final static String  DEFAULT_CHANNEL = "g";

	public static String dir = System.getProperty("imgdir", DEFAULT_DIR);
	public static String ext = System.getProperty("imgext", DEFAULT_EXT);
	public static String channel = System.getProperty("channel", DEFAULT_CHANNEL);

	float[][] features;
	String targetFile;
	int[] targets;
	int length = 0;
	int dimension = 0;
	float[][][] featuresperimage;
	String[] filenames;
	int[] targetclass;
	int[][] possitivetargetclassinfo; 
	int[][] negativetargetclassinfo; 
	int[][] trainingTargets;
	int maxClass;
	int i;
	int j;
	int k;
	int m;
	int cnts;
	int totalfeats=0;
	float x,y;

	private int numberofFeatures = 4;
	// closest/next closest neighbour distance ratio
	private float rod = 0.92f;
	ArrayList annotationLabels;

	DataInputDynamic problem = new DataInputDynamic(dir, ext, channel);

		public ConsensusSelection(float[][] features, String targetFile, String[] filenames, int[] targets,  annotool.io.DataInputDynamic problem) 
		{
		//discrete before mRMR selection
		this.features = features;
		this.targetFile = targetFile;
		this.targets = targets;
		this.filenames = filenames;
		this.problem = problem;
	}
		public ConsensusSelection(float[][] features, String targetFile, String[] filenames, int length, int[] targets,  DataInputDynamic problem) 
		{
		//discrete before mRMR selection
		this.features = features;
		this.targetFile = targetFile;
		this.targets = targets;
		this.length = length;
		this.filenames = filenames;
		this.problem = problem;
	}
	
	//return the selected features in vectors
	
	public float[][] select()
	{
		//ImagePlus[] data1 = problem.readImagePlus(dir,ext);
		featuresperimage = new float[features.length][][];

		
		//label reader

		int numOfAnno = 0;
		try
		{
			LabelReader labelReader = new LabelReader(length);
			trainingTargets = labelReader.getTargets(targetFile, filenames);
			maxClass = labelReader.getNumOfClasses();
			System.out.println("The number of classes is " +maxClass);
			annotationLabels = labelReader.getAnnotations();
			numOfAnno = labelReader.getNumOfAnnotations();
	
		}catch(Exception e)
		{   e.printStackTrace();
		}
		
		float[][] returnfeatures = new float[maxClass][];

		//-----  read targets matrix (for multiple annotations, one per column) --------//

		int a,b;
		targetclass = new int[length];
		possitivetargetclassinfo = new int[length][];
		negativetargetclassinfo = new int[length][];
		for(int i=0; i<numOfAnno; i++)
		{
			for(int j=0; j<trainingTargets[i].length; j++)
			{
				targetclass[j] = trainingTargets[i][j];
				//System.out.print(trainingTargets[i][j]+ "train ");
			}
		}
			i=0;
		for(int j=0; j<length; j++)
		{
			for(int i=0; i<numOfAnno; i++)
			{
				if(trainingTargets[i][j] == 1)
				{
					k = 0;
					m = 0;
					a = 0;
					b = 0;
					for(int sm=0; sm<trainingTargets[i].length; sm++)
					{
					
						if(trainingTargets[i][sm] == 1)
						{
							k++;
						}
					}
					possitivetargetclassinfo[j] = new int[k];

					for(int sm=0; sm<trainingTargets[i].length; sm++)
					{
					
						if(trainingTargets[i][sm] == 1)
						{
							possitivetargetclassinfo[j][a] = sm;
							a++;
						}
					}
				}
			}
		}
		if(numOfAnno == 1){
		for(i = 0; i < length; i++)
		{
			k = 0;
			m = 0;
			a = 0;
			b = 0;
			for(j = 0; j < length; j++)
			{
				if(targetclass[i] == targetclass[j])
				{
					//possitivetargetclassinfo[i][k] = j;
					//System.out.println("the ---"+possitivetargetclassinfo[i][k]);
					k++;
				}
				if(targetclass[i] != targetclass[j])
				{
					//negativetargetclassinfo[i][m] = j;
					//System.out.println("the nega ---"+negativetargetclassinfo[i][m]);
					m++;

				}
								
			}
			possitivetargetclassinfo[i] = new int[k];
			negativetargetclassinfo[i] = new int[m];
			for(j = 0; j < length; j++)
			{
				
				if(targetclass[i] == targetclass[j])
				{
					possitivetargetclassinfo[i][a] = j;
					//System.out.println("the ---"+possitivetargetclassinfo[i][a]);
					a++;
				}
				
				if(targetclass[i] != targetclass[j])
				{
					negativetargetclassinfo[i][b] = j;
					//System.out.println("the nega ---"+negativetargetclassinfo[i][b]);
					b++;

				}

				
			}

		}
		}
		
		//--------------------------------------------------------------------
		
		
		//--------------------------------------------------------------------
		//System.out.println("main ---"+possitivetargetclassinfo.length);

		for(int i = 0;i < features.length; i++)
		{
			featuresperimage[i] = new float[(features[i].length)/132][132];

			for(int j = 0;j < (features[i].length)/132; j++)
			{
			 
				for(int k = 0;k < 132;k++)
				{
					featuresperimage[i][j][k] = features[i][(j * 132) + k];
				}

			}
		 }
		
		
		ArrayList<Float> s1 = new ArrayList<Float>();
		
		ArrayList<Float> allratios = new ArrayList<Float>();	
		///
		int f = 0;
		for(int n = 0; n < features.length; n++)
		{
			//one cycle
			ArrayList<Float[]> allfeaturefloats =new ArrayList<Float[]>();
			ArrayList<Integer> allfeatureimages =new ArrayList<Integer>();
			ArrayList<Float> allfeatureweights =new ArrayList<Float>();
			ArrayList<fweights> allfeaturefweights =new ArrayList<fweights>();
			int[][][][] featurepositions = new int[maxClass][][][];
			for( int z = 0; z < possitivetargetclassinfo[n].length; z++)
			{
				i = possitivetargetclassinfo[n][z];
				float[][] ratio = new float[(possitivetargetclassinfo[n].length) - 1][];
				Float[][][] strs = new Float[(possitivetargetclassinfo[n].length) - 1][][];
				featurepositions[f] = new int[(possitivetargetclassinfo[n].length) - 1][][];
				Vector<Feature> testingfeat = new Vector<Feature>();
				for(int perfeat = 0; perfeat < featuresperimage[i].length; perfeat++)
					testingfeat.add(new Feature(featuresperimage[i][perfeat]));
				
				int e = 0; 	// initializing the pointer.

				for(int j = 0; j < possitivetargetclassinfo[n].length; j++)
				{	
					int k = possitivetargetclassinfo[n][j];
					if(k != i)
					{
					//System.out.println("the size of the 1st featureperimage s "+i+" and the is "+k);
					Vector<Feature> trainingfeat = new Vector<Feature>();
					for(int perfeat = 0; perfeat < featuresperimage[k].length; perfeat++)
						trainingfeat.add(new Feature(featuresperimage[k][perfeat]));
				    int[] candits = new int [length];
								
					Vector< PointMatch > candidates = 
							FloatArray2DSIFT.createMatches( testingfeat, trainingfeat, rod );
							candits[e] =candidates.size();
							float[] r_d = new float[candidates.size()];
							float[] d = new float[candidates.size()];
							Float[][][] featurefloats2d = new Float[(possitivetargetclassinfo[n].length) - 1][candidates.size()][132];
							Float[][][] featureFloats2d = new Float[(possitivetargetclassinfo[n].length) - 1][candidates.size()][132];
					        int[][] positions = new int[candidates.size()][2];
							int io=0;
							for ( PointMatch m : candidates )
							{
								
								r_d[io] = m.getrD();
								d[io] = m.getD();
								r_d[io] = r_d[io] * d[io];
								Feature fc = m.getfD();
								featurefloats2d[e][io] = fc.toFloats();
								positions[io][0] = testingfeat.indexOf(m.getfD());
								positions[io][1] = trainingfeat.indexOf(m.getf2Feature());
								//System.out.println("feature1 is: "+testingfeat.indexOf(m.getfD())+" and the feaure2 is : "+trainingfeat.indexOf(m.getf2Feature()));
								//quickSort.sort(r_d, featurefloats2d[e], 0, candidates.size()-1);
								io++;
							}
							Float[] rd = new Float[r_d.length];
								for(int ratiocount = 0; ratiocount < r_d.length; ratiocount++)
								{
									rd[ratiocount] = new Float(1 - ((r_d[ratiocount] ) ));
									//System.out.println("the rations are "+r_d[ratiocount] + " and the newformula made it to "+rd[ratiocount]);
								}
							for(int io1=0;io1<candidates.size();io1++)
							{
								for(int fsize = 0; fsize < 132; fsize++)
								{
							    	featureFloats2d[e][io1][fsize] = new Float(featurefloats2d[e][io1][fsize]);
								}
							}
							
							for(int io1=0;io1<candidates.size();io1++)
							{
								for(int cin = 0; cin < 132;cin++)
									s1.add(featureFloats2d[e][io1][cin]);
							    	allratios.add(rd[io1]);
							}
							ratio[e] = new float[rd.length];
							strs[e] = new Float[rd.length][132];
							featurepositions[f][e] = new int[rd.length][2];
							for(int inde=0;inde<candidates.size();inde++)
							{
								ratio[e][inde] = rd[inde];
						    	for(int fsize = 0; fsize < 132; fsize++)
						    		strs[e][inde][fsize] = featureFloats2d[e][inde][fsize];
						    	featurepositions[f][e][inde][0] = positions[inde][0];
						    	featurepositions[f][e][inde][1] = positions[inde][1];
							}
							for(int cani = 0; cani < candits.length; cani++)
							{
								totalfeats += candits[cani];
							}
							e++;  // incrementing array pointer
							
					} // end of if.
							
				}		// end of j		
				
				//----outside z loop
				int count =0;
				ArrayList<Float[]> all = new ArrayList<Float[]>();

				ArrayList<Float> aratio = new ArrayList<Float>();
				cnts = 0;
				cnts = totalfeats;
				ArrayList<fratios> frst = new ArrayList<fratios>();
				ArrayList<Integer> noslctfeat = new ArrayList<Integer>();
				ArrayList<Float[]> slctfeat = new ArrayList<Float[]>();

				int one;
				int featcount = 0;
				for(one = 0; one < strs.length; one++)
				{
					for(int two = 0; two < strs[one].length; two++)
					{
						for(int three=0;three<(features[i].length)/132;three++)
						{
								if(ratio[one][two] >= 0.5)
								{
									if(strs[one][two][0] == featuresperimage[i][three][0] && strs[one][two][1] == featuresperimage[i][three][1] && strs[one][two][2] == featuresperimage[i][three][2] && strs[one][two][3] == featuresperimage[i][three][3])
									{
										count++;
										noslctfeat.add((Integer)three);
										aratio.add(ratio[one][two]);
										all.add(strs[one][two]);
										slctfeat.add(strs[one][two]);
										frst.add(new fratios(strs[one][two],ratio[one][two]));
										featcount++;
									
									}

								}
						}
						 
					}
				}
				
				ArrayList<Float[]> sap = new ArrayList<Float[]>();
				ArrayList<Float> fap = new ArrayList<Float>();
				Collections.sort(frst);
				Float[][] al11= new Float[frst.size()][132];
				float[] al21= new float[frst.size()];
				for(fratios fr : frst)
				{					
					sap.add(fr.getfeats());
					fap.add(fr.getratio());					
				}
				

				for(int cn1=0;cn1<frst.size();cn1++)
				{
					al11[cn1] = sap.get(cn1);
					al21[cn1] = fap.get(cn1).floatValue();
				}
				
				ArrayList<Float[]> a1 = new ArrayList<Float[]>();
				a1=(ArrayList<Float[]>) sap.clone();
				
				ArrayList<Float[]> a2 = new ArrayList<Float[]>();
				a2=(ArrayList<Float[]>) sap.clone();
				
				ArrayList<Float> r1 = new ArrayList<Float>();
				r1=(ArrayList<Float>) fap.clone();
				
				ArrayList<Float> r2 = new ArrayList<Float>();
				r2=(ArrayList<Float>) fap.clone();
				
				HashSet hashSet = new HashSet(a1);

				  //Assign the HashSet to a new ArrayList
				ArrayList<Float[]> a12 = new ArrayList<Float[]>(hashSet) ;
				HashSet hashSet2 = new HashSet(r1);

				ArrayList<Float> r12 = new ArrayList<Float>(hashSet2) ;
				ArrayList<Float[]> an = new ArrayList<Float[]>();
				
				//------
				
				int[] indicount= new int[a1.size()];
				float[] avgr = new float[r2.size()];
				ArrayList<Float[]> allfinalfeat = new ArrayList<Float[]>();
				ArrayList<Float> allfinalavg = new ArrayList<Float>();
				ArrayList<Integer> allfinalcount = new ArrayList<Integer>();
				ArrayList<fweights> fweight = new ArrayList<fweights>();
				
				ArrayList<Integer> duplicates = new ArrayList<Integer>();
				for(int loopvar1 = 0; loopvar1 < a1.size(); loopvar1++)
				{
					if(!duplicates.contains(loopvar1))
					{
					avgr[loopvar1] = 0;
					indicount[loopvar1] = 0;
					for(int loopvar2 = 0; loopvar2 < a2.size(); loopvar2++)
					{
						if(a1.get(loopvar1)[0].floatValue() == a2.get(loopvar2)[0].floatValue() && a1.get(loopvar1)[2].floatValue() == a2.get(loopvar2)[2].floatValue() && a1.get(loopvar1)[3].floatValue() == a2.get(loopvar2)[3].floatValue() && a1.get(loopvar1)[1].floatValue() == a2.get(loopvar2)[1].floatValue())
						{
							  duplicates.add(loopvar2);	
							  avgr[loopvar1]=avgr[loopvar1]+r2.get(loopvar2);
							  indicount[loopvar1]++;
						}
					}
					avgr[loopvar1] = avgr[loopvar1] / (possitivetargetclassinfo[n].length - 1);
					float fra = avgr[loopvar1];
					fweight.add(new fweights(a1.get(loopvar1),fra));
					allfinalfeat.add(a1.get(loopvar1));
					allfinalavg.add(avgr[loopvar1]);
					allfinalcount.add(indicount[loopvar1]);
					
					}
				}
				Collections.sort(fweight);
				Float[][] finalsortfeats = new Float[fweight.size()][132];
				float[] finalsortweights= new float[fweight.size()];
				int fms=0;
				for(fweights fw:fweight)
				{
					if(fw.getweight()!=0.0)
					{
					finalsortfeats[fms]=fw.getfeats();
					finalsortweights[fms]=fw.getweight();
					fms++;
					}
				}
				Float[] featarray = new Float[132];
				float[] finalsortFeats = new float[finalsortfeats.length * 132];

				for(int value=0;value<finalsortfeats.length;value++)
				{
					for(int arraycount =0 ;arraycount < 132;arraycount++)
					{
						featarray[arraycount] = finalsortfeats[value][arraycount];
						finalsortFeats[(value * 132) + arraycount] = finalsortfeats[value][arraycount];
					}
					allfeaturefloats.add(featarray);
					allfeatureweights.add(finalsortweights[value]);
					allfeatureimages.add(i);
							
				}
		  } //end of z for
			for(int num=0;num<allfeaturefloats.size();num++)
			{
				allfeaturefweights.add(new fweights(allfeaturefloats.get(num), allfeatureweights.get(num), allfeatureimages.get(num)));
			}
			Collections.sort(allfeaturefweights);
			Float[][] finalsortfeats = new Float[allfeaturefweights.size()][132];
            Integer[] imagenumber = new Integer[allfeatureimages.size()];
			float[] finalsortweights= new float[allfeaturefweights.size()];
			int fms=0;
			
			for(fweights fw:allfeaturefweights)
			{
				if(fw.getweight()!=0.0)
				{
				finalsortfeats[fms]=fw.getfeats();
				finalsortweights[fms]=fw.getweight();
				imagenumber[fms] = fw.getimageNumber();
				
				fms++;
				}
			}
			ArrayList<Float[]> featfloats = new ArrayList<Float[]>();
			for(int value=0;value<finalsortfeats.length;value++)
			{
				
				featfloats.add(finalsortfeats[value]);
				//System.out.println("the ges"+finalsortfeats[value][0]+" "+finalsortfeats[value][1]+" "+finalsortfeats[value][2]+" "+finalsortfeats[value][3]+" ");

			}
			//System.out.println("the size would be: "+featfloats.size());

			ArrayList<Float[]> a1 = new ArrayList<Float[]>();
			a1=(ArrayList<Float[]>) featfloats.clone();
			
			ArrayList<Float[]> a2 = new ArrayList<Float[]>();
			a2=(ArrayList<Float[]>) featfloats.clone();
									
			HashSet hashSet = new HashSet(a1);

			  //Assign the HashSet to a new ArrayList
			ArrayList<Float[]> a12 = new ArrayList<Float[]>(hashSet) ;
			int[] indicount= new int[a1.size()];
			ArrayList<Float[]> allfinalfeat = new ArrayList<Float[]>();
			ArrayList<Float> allfinalavg = new ArrayList<Float>();
			ArrayList<Integer> allfinalcount = new ArrayList<Integer>();
			ArrayList<fweights> fweight = new ArrayList<fweights>();
			
			ArrayList<Integer> duplicates = new ArrayList<Integer>();
			for(int loopvar1 = 0; loopvar1 < a1.size(); loopvar1++)
			{
				if(!duplicates.contains(loopvar1))
				{
				indicount[loopvar1] = 0;
				for(int loopvar2 = 0; loopvar2 < a2.size(); loopvar2++)
				{
					//System.out.println("the loopvars are"+loopvar1+"and "+loopvar2);
					if(a1.get(loopvar1)[0].floatValue() == a2.get(loopvar2)[0].floatValue() && a1.get(loopvar1)[2].floatValue() == a2.get(loopvar2)[2].floatValue() && a1.get(loopvar1)[3].floatValue() == a2.get(loopvar2)[3].floatValue() && a1.get(loopvar1)[1].floatValue() == a2.get(loopvar2)[1].floatValue())
					{
						  duplicates.add(loopvar2);	
						  indicount[loopvar1]++;
							//System.out.println("the sample out is : "+a1.get(loopvar1)[0].floatValue()+" the sample out is : "+a1.get(loopvar1)[1].floatValue()+" the sample out is : "+a1.get(loopvar1)[2].floatValue()+"the sample out is : "+a1.get(loopvar1)[3].floatValue()+" nd avg is "+avgr[loopvar1]+"&& count is "+indicount[loopvar1]+"the ratios is "+ r2.get(loopvar2));
						}
				}
				//float fra = weights.weight((float)indicount[loopvar1],(float)((possitivetargetclassinfo[n].length) - 1),avgr[loopvar1]);
				allfinalfeat.add(a1.get(loopvar1));
				allfinalcount.add(indicount[loopvar1]);
			//	System.out.println("the final avg is "+avgr[loopvar1]);
				
				}
			}
			ArrayList<Float> featfloat = new ArrayList<Float>();
			Float[] featarrays = new Float[132];
			for(int value=0;value<allfinalfeat.size();value++)
			{
				featarrays = allfinalfeat.get(value);
				//System.out.println("the ges"+featarrays[0]+" "+featarrays[1]+" "+featarrays[2]+" "+featarrays[3]+" ");
				for(int arraycount =0 ;arraycount < 132;arraycount++)
				{
					featfloat.add(featarrays[arraycount]);
				}
			}
			System.out.println("the size would be: "+featfloat.size());
			returnfeatures[f] =  new float[numberofFeatures * 132];
			int[] numberimage = new int[numberofFeatures]; 
			for(int num = 0;num < numberofFeatures ;num++)
			{
				numberimage[num] = imagenumber[num];
				for(int num1 = 0; num1 < 132; num1++)
				{
					returnfeatures[f][(num * 132) + num1] = (float)featfloat.get((num * 132) + num1);
				}
				

			}
			/*for(int num = 0 ; num < possitivetargetclassinfo[n].length; num ++)
			{
				ArrayList<Integer> imageposition = new ArrayList<Integer>();
				ArrayList<Float> featureposition = new ArrayList<Float>();
				for(int num2 = 0; num2 < numberofFeatures; num2++)
				{
					if(possitivetargetclassinfo[n][num] == numberimage[num2])
					{
						imageposition.add(numberimage[num2]);
						for(int num1 = 0; num1 < 132; num1++)
						{
							featureposition.add(returnfeatures[f][(num2 * 132) + num1]);
						}
					}
				}
				float[] featposition = new float[imageposition.size()*132];
				for(int position = 0; position < imageposition.size(); position++)
				{
					for(int num1 = 0; num1 < 132; num1++)
					{
						featposition[(position * 132) + num1] = (float)featureposition.get((position * 132) + num1);
					}
				}
				Visualization visual = new Visualization(data1[possitivetargetclassinfo[n][num]], featposition); 
				visual.show();
			}*/
			System.out.print("The size would be  "+returnfeatures[f].length);
			n =  n + (possitivetargetclassinfo[n].length);
			f++;
		}  //end of i for
		
		///
		System.out.println("\n\n\nend of new code\n\n\n");

		return returnfeatures;
				
}

	
	

	
}
	